package com.vegasoft.games.tetrixml;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class Piece implements Serializable {

	/** serialVersion UID
	 * 
	 */
	private static final long serialVersionUID = 7255802495610371963L;
	
	private Coordinate position = new Coordinate();
	private Grid shape;
	private List<PieceEventListener> listeners = new ArrayList<PieceEventListener>();
	
	public Piece(Grid shape) {
		this.shape = shape;
	}
	
	/**
	 * @return the x position
	 */
	public int getXPosition() {
		if(position == null)
			return -1;
		return position.getX();
	}
	
	/**
	 * @return the y position
	 */
	public int getYPosition() {
		if(position == null)
			return -1;
		return position.getY();
	}
	
	/**
	 * @return the shape
	 */
	public Grid getShape() {
		return shape;
	}
	
	public void rightRotate() {
		performeRightRotation();
		PieceEventArgs<Serializable> event = new PieceEventArgs<Serializable>(PieceEventAction.RightRotation, this);
		notifyListeners(event);
	}
	
	public void leftRotate() {
		performeRightRotation();
		performeRightRotation();
		performeRightRotation();
		PieceEventArgs<Serializable> event = new PieceEventArgs<Serializable>(PieceEventAction.LeftRotation, this);
		notifyListeners(event);
	}
	
	protected void notifyListeners(PieceEventArgs<Serializable> event) {
		if(listeners != null) {
			for(PieceEventListener listener : listeners) {
				listener.listen(this, event);
			}
		}
	}
	
	protected void performeRightRotation() {
		if(shape != null) {
			Grid newShape = new Grid(shape.getRows(), shape.getColumns());
			for(int y=0; y < shape.getRows(); y++) {
				for(int x=0; x < shape.getColumns(); x++) {
					newShape.getGeometry()[x][y] = shape.getGeometry()[shape.getRows()-1-y][x];
				}
			}
			this.shape = newShape;
		}
	}
	
	public static void main(String[] args) {
		Grid prova = new Grid(3,2);
		prova.getGeometry()[0][0] = true;
		prova.getGeometry()[0][1] = false;
		prova.getGeometry()[0][2] = false;
		prova.getGeometry()[1][0] = true;
		prova.getGeometry()[1][1] = true;
		prova.getGeometry()[1][2] = true;
		
		Piece piece = new Piece(prova);
		
		draw(prova);
		
		piece.rightRotate();
		System.out.println("\nRotate Right\n");
		
		draw(piece.getShape());
		
		piece.rightRotate();
		System.out.println("\nRotate Right\n");
		
		draw(piece.getShape());
		
		piece.rightRotate();
		System.out.println("\nRotate Right\n");
		
		draw(piece.getShape());
		
		piece.leftRotate();
		System.out.println("\nRotate Left\n");
		
		draw(piece.getShape());
	}
	
	private static void draw(Grid grid) {
		if(grid != null) {
			boolean[][] shape = grid.getGeometry();
			for(int y=0; y < grid.getRows(); y++) {
				for(int x=0; x < grid.getColumns(); x++) {
					if(shape[y][x])
						System.out.print("@");
					else
						System.out.print(" ");
				}
				System.out.println("");
			}
		}
	}
	
	public void addListener(PieceEventListener listener) {
		listeners.add(listener);
	}
	
	public void removeListener(PieceEventListener listener) {
		listeners.remove(listener);
	}
	
	public void moveLeft() {
		move(Direction.Left, 1);
	}
	
	public void moveRight() {
		move(Direction.Right, 1);
	}
	
	public void moveDown() {
		move(Direction.Down, 1);	
	}
	
	protected void move(Direction direction, int step) {
		PieceEventAction action;
		if(direction == null) return;
		
		if(direction == Direction.Left) {
			this.position.setX(-step);
			action = PieceEventAction.LeftMove;
		}
		else if(direction == Direction.Right) {
			this.position.setX(step);
			action = PieceEventAction.RightMove;
		}
		else if(direction == Direction.Down) {
			this.position.setY(-step);
			action = PieceEventAction.DownMove;
		}
		else {
			//Nothing
			return;
		}
		
		PieceEventArgs<Serializable> event = new PieceEventArgs<Serializable>(action, this);
		notifyListeners(event);
	}
}
